<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Test for page errors</title>
  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript;version=1.8" src="common.js"></script>
  <!-- Any copyright is dedicated to the Public Domain.
     - http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<p>Test for page errors</p>

<script class="testbody" type="text/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();

let expectedPageErrors = [];

function doPageErrors()
{
  expectedPageErrors = {
    "document.body.style.color = 'fooColor';": {
      errorMessage: /fooColor/,
      errorMessageName: undefined,
      sourceName: /test_page_errors/,
      category: "CSS Parser",
      timeStamp: /^\d+$/,
      error: false,
      warning: true,
      exception: false,
      strict: false,
    },
   "document.doTheImpossible();": {
      errorMessage: /doTheImpossible/,
      errorMessageName: undefined,
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
      strict: false,
    },
    "(42).toString(0);": {
      errorMessage: /radix/,
      errorMessageName: "JSMSG_BAD_RADIX",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
      strict: false,
    },
     "'use strict'; (Object.freeze({name: 'Elsa', score: 157})).score = 0;": {
      errorMessage: /read.only/,
      errorMessageName: "JSMSG_READ_ONLY",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
    },
     "([]).length = -1": {
      errorMessage: /array length/,
      errorMessageName: "JSMSG_BAD_ARRAY_LENGTH",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
    },
     "'abc'.repeat(-1);": {
      errorMessage: /repeat count.*non-negative/,
      errorMessageName: "JSMSG_NEGATIVE_REPETITION_COUNT",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
    },
    "'a'.repeat(2e28);": {
      errorMessage: /repeat count.*less than infinity/,
      errorMessageName: "JSMSG_RESULTING_STRING_TOO_LARGE",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
    },
    "77.1234.toExponential(-1);": {
      errorMessage: /out of range/,
      errorMessageName: "JSMSG_PRECISION_RANGE",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
    },
    "function a() { return; 1 + 1; }": {
      errorMessage: /unreachable code/,
      errorMessageName: "JSMSG_STMT_AFTER_RETURN",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: true,
      exception: false,
    },
    "let a, a;": {
      errorMessage: /redeclaration of/,
      errorMessageName: "JSMSG_REDECLARED_VAR",
      sourceName: /test_page_errors/,
      category: "chrome javascript",
      timeStamp: /^\d+$/,
      error: false,
      warning: false,
      exception: true,
      notes: [
        {
          messageBody: /Previously declared at line/,
          frame: {
            source: /test_page_errors/,
          }
        }
      ]
    },
  };

  let container = document.createElement("script");
  for (let stmt of Object.keys(expectedPageErrors)) {
      if (expectedPageErrors[stmt].exception) {
          SimpleTest.expectUncaughtException();
      }
      info("starting stmt: " + stmt);
      container = document.createElement("script");
      document.body.appendChild(container);
      container.textContent = stmt;
      document.body.removeChild(container);
      info("ending stmt: " + stmt);
  }
}

function startTest()
{
  removeEventListener("load", startTest);

  attachConsole(["PageError"], onAttach);
}

function onAttach(aState, aResponse)
{
  onPageError = onPageError.bind(null, aState);
  aState.dbgClient.addListener("pageError", onPageError);
  doPageErrors();
}

let pageErrors = [];

function onPageError(aState, aType, aPacket)
{
  if (!aPacket.pageError.sourceName.includes("test_page_errors")) {
    info("Ignoring error from unknown source: " + aPacket.pageError.sourceName);
    return;
  }

  is(aPacket.from, aState.actor, "page error actor");

  pageErrors.push(aPacket.pageError);
  if (pageErrors.length != Object.keys(expectedPageErrors).length) {
    return;
  }

  aState.dbgClient.removeListener("pageError", onPageError);

  Object.values(expectedPageErrors).forEach(function(aMessage, aIndex) {
    info("checking received page error #" + aIndex);
    checkObject(pageErrors[aIndex], Object.values(expectedPageErrors)[aIndex]);
  });

  closeDebugger(aState, function() {
    SimpleTest.finish();
  });
}

addEventListener("load", startTest);
</script>
</body>
</html>
